﻿using System.Collections.Generic;
using PgBirdie.Core.Extensions;
using PgBirdie.Core.Model.Database.AccessControl;
using PgBirdie.Core.Model.Database.Structure;
using PgBirdie.Core.Model.Database.Structure.Constraint;
using PgBirdie.Core.Model.Database.Structure.Index;

namespace PgBirdie.Core.Service.DbObject
{
    public class DbObjectFromDbService : IDbObjectFromDbService
    {
        public IDictionary<string, PgSequence> GetAllSequences(PgDatabase db)
        {
            var items = new Dictionary<string, PgSequence>();

            foreach (var schema in db.Schemas.Values)
                foreach (var sequence in schema.Sequences.Values)
                    if (sequence != null)
                        items.Add(string.Format("{0}.{1}", schema.Name, sequence.Name), sequence);

            return items;
        }

        public IDictionary<string, PgTable> GetAllTables(PgDatabase db)
        {
            var items = new Dictionary<string, PgTable>();

            foreach (var schema in db.Schemas.Values)
                foreach (var table in schema.Tables.Values)
                    if (table != null)
                        items.Add(string.Format("{0}.{1}", schema.Name, table.Name), table);

            return items;
        }

        public IDictionary<string, PgColumn> GetAllColumns(PgDatabase db)
        {
            var items = new Dictionary<string, PgColumn>();

            foreach (var schema in db.Schemas.Values)
                foreach (var table in schema.Tables.Values)
                    foreach (var column in table.Columns.Values)
                        if (column != null)
                            items.Add(string.Format("{0}.{1}|{2}", schema.Name, table.Name, column.Name), column);

            return items;
        }

        public IDictionary<string, PgIndex> GetAllIndexes(PgDatabase db)
        {
            var items = new Dictionary<string, PgIndex>();

            foreach (var schema in db.Schemas.Values)
                foreach (var table in schema.Tables.Values)
                    foreach (var index in table.Indexes.Values)
                        if (index != null)
                            items.Add(string.Format("{0}.{1}", schema.Name, index.Name), index);

            return items;
        }

        public IDictionary<string, PgConstraintBase> GetAllConstraints(PgDatabase db)
        {
            var items = new Dictionary<string, PgConstraintBase>();

            foreach (var schema in db.Schemas.Values)
                foreach (var table in schema.Tables.Values)
                    items.Add(string.Format("{0}.{1}", schema.Name, table.PrimaryKey.Name), table.PrimaryKey);

            foreach (var schema in db.Schemas.Values)
                foreach (var table in schema.Tables.Values)
                    if (table.UniqueKeys.IsNotNullOrEmpty())
                        foreach (var key in table.UniqueKeys.Values)
                            items.Add(string.Format("{0}.{1}", schema.Name, key.Name), key);

            foreach (var schema in db.Schemas.Values)
                foreach (var table in schema.Tables.Values)
                    if (table.ForeignKeys.IsNotNullOrEmpty())
                        foreach (var key in table.ForeignKeys.Values)
                            if (key != null)
                                items.Add(string.Format("{0}.{1}", schema.Name, key.Name), key);

            return items;
        }

        public IDictionary<string, PgPrimaryKey> GetAllPrimaryKeys(PgDatabase db)
        {
            var items = new Dictionary<string, PgPrimaryKey>();

            foreach (var schema in db.Schemas.Values)
                foreach (var table in schema.Tables.Values)
                    if (table.PrimaryKey != null)
                        items.Add(string.Format("{0}.{1}", schema.Name, table.PrimaryKey.Name), table.PrimaryKey);

            return items;
        }

        public IDictionary<string, PgUniqueKey> GetAllUniqueKeys(PgDatabase db)
        {
            var items = new Dictionary<string, PgUniqueKey>();

            foreach (var schema in db.Schemas.Values)
                foreach (var table in schema.Tables.Values)
                    foreach (var key in table.UniqueKeys.Values)
                        items.Add(string.Format("{0}.{1}", schema.Name, key.Name), key);

            return items;
        }

        public IDictionary<string, PgForeignKey> GetAllForeignKeys(PgDatabase db)
        {
            var items = new Dictionary<string, PgForeignKey>();

            foreach (var schema in db.Schemas.Values)
                foreach (var table in schema.Tables.Values)
                    foreach (var key in table.ForeignKeys.Values)
                        items.Add(string.Format("{0}.{1}", schema.Name, key.Name), key);

            return items;
        }

        public IDictionary<string, PgOwner> GetAllOwners(PgDatabase db)
        {
            var items = new Dictionary<string, PgOwner>();

            items.Add(db.Owner.Id, db.Owner);

            foreach (var schema in db.Schemas.Values)
            {
                items.Add(schema.Owner.Id, schema.Owner);
                foreach (var table in schema.Tables.Values)
                    items.Add(string.Format("{0}.{1}", schema.Name, table.Owner.Id), table.Owner);
            }

            return items;
        }

        public IDictionary<string, PgPrivilege> GetAllPrivileges(PgDatabase db)
        {
            var items = new Dictionary<string, PgPrivilege>();

            foreach (var dbPriv in db.Privileges)
                items.Add(dbPriv.Key, dbPriv.Value);

            foreach (var schema in db.Schemas.Values)
            {
                foreach (var schemaPriv in schema.Privileges)
                    items.Add(schemaPriv.Key, schemaPriv.Value);

                foreach (var sequence in schema.Sequences.Values)
                    foreach (var sequencePriv in sequence.Privileges)                        
                        items.Add(string.Format("{0}.{1}", schema.Name, sequencePriv.Key), sequencePriv.Value);

                foreach (var table in schema.Tables.Values)
                    foreach (var tablePriv in table.Privileges)
                        items.Add(string.Format("{0}.{1}", schema.Name, tablePriv.Key), tablePriv.Value);
            }

            return items;
        }
    }
}